package com.hqyj.user.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hqyj.config.SmsConfig;
import com.hqyj.user.dto.UserInfo;
import com.hqyj.user.entity.User;
import com.hqyj.user.mapper.UserMapper;
import com.hqyj.user.pojo.MyNode;
import com.hqyj.user.pojo.UserRole;
import com.hqyj.user.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hqyj.utils.MdUtils;
import com.hqyj.utils.PageUtil;
import com.hqyj.utils.ResultUtils;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import jdk.nashorn.internal.ir.ReturnNode;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.management.relation.Role;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author sdx2009
 * @since 2022-09-30
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private JavaMailSender javaMailSender;

    @Value("${spring.mail.username}")
    private String fromEmail;

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private SmsConfig smsConfig;

    @Autowired
    private SmsClient smsClient;

    @Resource
    private UserMapper userMapper;

    @Override
    public User login(User user) {
        QueryWrapper<User> qw = new QueryWrapper<>();
        if (user.getUserName() != null && user.getUserName() != ""){
            qw.eq("user_name",user.getUserName());
        }
        if (user.getUserEmail() != null && user.getUserEmail() != ""){
            qw.eq("user_email",user.getUserEmail());
        }
        if (user.getUserTel() != null && user.getUserTel() != ""){
            qw.eq("user_tel",user.getUserTel());
        }
        return this.getOne(qw);
    }

    @Override
    public ResultUtils sendEmailCode(String userEmail) {
        User user = new User();
        user.setUserEmail(userEmail);
        user = login(user);
        if (Objects.isNull(user)){
            return new ResultUtils(401,"邮箱未注册!",null);
        }
        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setTo(userEmail);
            message.setFrom(fromEmail);
            message.setSubject("京东公司验证码");
            String code = (int)(Math.random()*10000 + 1000) + "";
            message.setText("你的验证码是：" + code);
            javaMailSender.send(message);
            String key = "EmailCode:" + userEmail;
            redisTemplate.opsForValue().set(key,code,1, TimeUnit.MINUTES);
            redisTemplate.opsForValue().set("user",user);
        }catch (Exception e){
            e.printStackTrace();
            return new ResultUtils(401,"发送失败！",null);
        }

        return new ResultUtils(200,"发送成功！",null);
    }

    @Override
    public ResultUtils emailLogin(UserInfo userInfo) {
        return validationCode(userInfo,0);
    }

    @Override
    public ResultUtils sendSmsCode(String tel) {
        User user = new User();
        user.setUserTel(tel);
        user = login(user);
        if (Objects.isNull(user)){
            return new ResultUtils(401,"电话未注册!",null);
        }
        SendSmsRequest request = new SendSmsRequest();
        String[] p = {tel};
        request.setPhoneNumberSet(p);
        request.setTemplateId(smsConfig.getSecretId());
        request.setSmsSdkAppId(smsConfig.getSmsSdk());
        request.setSignName(smsConfig.getSmsName());
        String code = (int)(Math.random()*10000 + 1000) + "";
        String[] c = {code};
        request.setTemplateParamSet(c);
        try {
            SendSmsResponse res = smsClient.SendSms(request);
            ObjectMapper mapper = new ObjectMapper();
            Map<String,Object> map = mapper.readValue(SendSmsRequest.toJsonString(res),Map.class);
            List<HashMap<String,String>> list = (List<HashMap<String, String>>) map.get("SendStatusSet");
            if (list.get(0).get("Code").equals("Ok")){
                String key = "TelCode:" + tel;
                redisTemplate.opsForValue().set(key,code,1,TimeUnit.MINUTES);
                redisTemplate.opsForValue().set("user",user);
            }
        }catch (Exception e){
            e.printStackTrace();
            return new ResultUtils(401,"发送失败!",null);
        }
        return new ResultUtils(200,"发送成功！!",null);
    }

    @Override
    public ResultUtils smsLogin(UserInfo userInfo) {
        return validationCode(userInfo,1);
    }

    /**
     * 根据用户名查权限
     * @param userName
     * @return
     */
    @Override
    public ResultUtils queryByName(String userName) {
        List<MyNode> myNodes = userMapper.queryByName(userName);
        List<MyNode> list = new LinkedList<>();
        for (int i = 0;i < myNodes.size();i++){
            if (myNodes.get(i).getParentId() == 0){
                List<MyNode> listChildren = new LinkedList<>();
                for (int j = 0;j < myNodes.size();j++){
                    if (myNodes.get(j).getParentId() == myNodes.get(i).getNodeId()){
                        listChildren.add(myNodes.get(j));
                    }
                }
                myNodes.get(i).setChildren(listChildren);
                list.add(myNodes.get(i));
            }
        }
        return new ResultUtils(200,"",list);
    }

    @Override
    public ResultUtils selectUserByUserName() {
        Object user = redisTemplate.opsForValue().get("user");
        return new ResultUtils(200,"",user);
    }

    @Override
    public ResultUtils updateUserByUserName(UserInfo userInfo) {
        User user = new User();
        String password = MdUtils.changePassword(userInfo.getUserName(),userInfo.getUserPwd());
        BeanUtils.copyProperties(userInfo,user);
        user.setUserPwd(password);
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("user_name",userInfo.getUserName());
        if (this.update(user, wrapper)){
            redisTemplate.opsForValue().set("user",user);
            return new ResultUtils(200,"修改成功",null);
        }
        return new ResultUtils(500,"修改失败",null);
    }

    @Override
    public ResultUtils userIndex(UserInfo userInfo) {
        Page<UserRole> page = new Page<>(userInfo.getPage(),userInfo.getRow());
        Page<UserRole> pageList = userMapper.queryUserRole(page, userInfo);
        PageUtil<UserRole> pageUtil = new PageUtil<>();
        pageUtil.setData(pageList.getRecords());
        pageUtil.setTotal(pageList.getTotal());
        pageUtil.setTotalPage(pageList.getPages());
        return new ResultUtils(200,"",pageUtil);
    }

    @Transactional
    @Override
    public ResultUtils updateOtherUser(UserInfo userInfo) {
        User user = new User();
        String password = MdUtils.changePassword(userInfo.getUserName(),userInfo.getUserPwd());
        BeanUtils.copyProperties(userInfo,user);
        user.setUserPwd(password);
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("user_name",userInfo.getUserName());
        if (this.update(user, wrapper)){
            int i = userMapper.updateRoleById(userInfo.getUserRole(), userInfo.getUserId());
            if (i > 0){
                return new ResultUtils(200,"修改成功",null);
            }
        }
        return new ResultUtils(500,"修改失败",null);
    }

    @Transactional
    @Override
    public ResultUtils deleteUser(UserInfo userInfo) {
        if (this.removeById(userInfo.getUserId())){
            int i = userMapper.deleteUserRoleByUserId(userInfo.getUserId());
            if (i > 0){
                return new ResultUtils(200,"删除成功",null);
            }
        }
        return new ResultUtils(500,"删除失败",null);
    }

    @Transactional
    @Override
    public ResultUtils addUser(UserInfo userInfo) {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.eq("user_name", userInfo.getUserName());
        if (this.getOne(qw) != null){
            return new ResultUtils(500,"用户名重复",null);
        }
        User user = new User();
        BeanUtils.copyProperties(userInfo,user);
        user.setUserPwd(MdUtils.changePassword(userInfo.getUserName(),userInfo.getUserPwd()));
        if (this.save(user)){
            User user1 = this.getOne(qw);
            if (userMapper.addUserRole(user1.getUserId(), userInfo.getUserRole() == "admin" ? 1 : 2) > 0){
                return new ResultUtils(200,"添加成功",null);
            }
        }
        return new ResultUtils(500,"添加失败",null);
    }

    @Override
    public ResultUtils selectUser() {
        return new ResultUtils(200,"",userMapper.selectUser());
    }

    @Override
    public ResultUtils logOut() {
        if (redisTemplate.delete("user") && !Objects.isNull(SecurityUtils.getSubject().getSession().removeAttribute("user"))){
            return new ResultUtils(200,"退出成功！",null);
        }
        return new ResultUtils(500,"退出失败！",null);
    }

    /**
     * 验证Code
     * @param userInfo
     * @param i 0代表邮箱验证 1代表短信验证
     * @return
     */
    public ResultUtils validationCode(UserInfo userInfo,int i){
        String key = i == 0 ? "EmailCode:" + userInfo.getUserEmail():"TelCode:" + userInfo.getUserTel();
        Object code = redisTemplate.opsForValue().get(key);
        if (Objects.isNull(code)){
            return new ResultUtils(401,"验证码超时！",null);
        }else {
            if (!code.equals(userInfo.getCode())){
                return new ResultUtils(401,"验证码输入错误！",null);
            }
        }
        User user = (User)redisTemplate.opsForValue().get("user");
        Subject subject = SecurityUtils.getSubject();
        subject.getSession().setAttribute("user",user);
        return new ResultUtils(200,"允许登录！",user);
    }


}
